package com.yingeo.ai.sdk.demo;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatEditText;
import androidx.appcompat.widget.SwitchCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.listener.OnItemClickListener;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import com.yingeo.ai.sdk.aidl.ActiveUserInfo;
import com.yingeo.ai.sdk.aidl.AiErrorMessage;
import com.yingeo.ai.sdk.aidl.AiGoodsBean;
import com.yingeo.ai.sdk.aidl.AiRecognitionResult;
import com.yingeo.ai.sdk.aidl.AiRemoteResponse;
import com.yingeo.ai.sdk.aidl.ErrorCode;
import com.yingeo.ai.sdk.aidl.YingeoAiConfig;
import com.yingeo.ai.sdk.client.YingeoAiSDK;
import com.yingeo.ai.sdk.client.callback.IYingeoAIServiceCallback;
import com.yingeo.ai.sdk.client.commons.enums.AiSettingType;
import com.yingeo.ai.sdk.client.utils.ListUtils;
import com.yingeo.ai.sdk.client.utils.MLog;
import com.yingeo.ai.sdk.demo.common.GoodsResultSource;
import com.yingeo.ai.sdk.demo.goods.GoodsBean;
import com.yingeo.ai.sdk.demo.goods.GoodsDataSource;
import com.yingeo.ai.sdk.demo.utils.GridLayoutDecoration;
import com.yingeo.ai.sdk.demo.utils.MainHandler;
import com.yingeo.ai.sdk.demo.utils.NavigationBarUtil;

import java.util.ArrayList;
import java.util.List;

import me.jessyan.autosize.AutoSizeConfig;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, Handler.Callback {

    private static final String TAG = MainActivity.class.getSimpleName();

    private YingeoAiSDK mYingeoAiSDK;
    private final List<GoodsBean> goodsList = new ArrayList<>();
    private GoodsAdapter goodsAdapter;
    // 商品结果来源
    private GoodsResultSource goodsResultSource = GoodsResultSource.SEARCH;
    private ImageView ivPreview;
    private TextView totalCountView;
    private TextView willPayView;
    private TextView realPayIntView;
    private TextView realPayFloatView;
    private Handler handler;
    private String totalPrice = "";


    public void hideKeyboard(View view){
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm != null) {
            imm.hideSoftInputFromWindow(view.getWindowToken(),0x0002);
        }
    }

    @Override
    public boolean handleMessage(@NonNull Message msg) {
        if (msg.what == 1) {
            if (mYingeoAiSDK != null) {
                executeAiRecognition();
            }
        }
        if (msg.what == 2) {
            hideKeyboard((View) msg.obj);
        }
        if (msg.what == 3) {
            goodsList.clear();
            goodsAdapter.notifyDataSetChanged();
        }
        if (msg.what == 4) {
            handler.sendEmptyMessage(1);
            handler.sendEmptyMessageDelayed(4, 500);
        }
        return true;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // 横屏ui适配
        AutoSizeConfig.getInstance().setDesignWidthInDp(1920).setDesignHeightInDp(1080);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_ui);
        NavigationBarUtil.hideNavigationBar(this);

        View btnAiRecognition = findViewById(R.id.btnAiRecognition);
        View btnAiSetting = findViewById(R.id.btnAiSetting);
        View surePay = findViewById(R.id.sure_pay);
        ivPreview = findViewById(R.id.ivPreview);
        totalCountView = findViewById(R.id.total_count);
        willPayView = findViewById(R.id.will_pay);
        realPayIntView = findViewById(R.id.real_pay_int_part);
        realPayFloatView = findViewById(R.id.real_pay_float_part);

        handler = new Handler(this);
        final AppCompatEditText textInput = findViewById(R.id.text_input);
        textInput.requestFocus();
        Message msg = handler.obtainMessage(2, textInput);
        handler.sendMessageDelayed(msg, 2000);
        textInput.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if ("228899".equals(s.toString())) {
                    handler.sendEmptyMessage(1);
                    textInput.setText("");
                }
            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        });
        SwitchCompat aiTimer = findViewById(R.id.ai_timer);
        aiTimer.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (isChecked) {
                handler.sendEmptyMessageDelayed(4, 100);
            } else {
                handler.removeMessages(4);
            }
        });

        btnAiRecognition.setOnClickListener(this);
        btnAiSetting.setOnClickListener(this);
        surePay.setOnClickListener(this);

        initGoodsListView();

        initAiSDK();
    }

    private void initGoodsListView() {
        RecyclerView recyclerView = findViewById(R.id.recyclerView);
        recyclerView.addItemDecoration(new GridLayoutDecoration(5, 10, 20));
        recyclerView.setLayoutManager(new GridLayoutManager(this, 5));
        goodsAdapter = new GoodsAdapter(goodsList);
        recyclerView.setAdapter(goodsAdapter);
        goodsAdapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
                GoodsBean goodsBean = goodsList.get(position);

                // 增量同步该商品到ai端
                ArrayList<AiGoodsBean> list = new ArrayList<>();
                AiGoodsBean aiGoodsBean = convertGoodsInfo2AiGoodsBean(goodsBean);
                list.add(aiGoodsBean);
                AiRemoteResponse doSyncGoodsResponse = mYingeoAiSDK.doSyncGoods(list);
                MLog.d(TAG, "指定商品进行学习 》》》增量同步指定商品 : response = " + doSyncGoodsResponse);

                // 对该商品进行学习
                if (goodsResultSource == GoodsResultSource.SEARCH) {
                    // 指定商品进行学习
                    AiRemoteResponse response = mYingeoAiSDK.aiLearnWithGoods(goodsBean.getGoodsCode());
                    MLog.d(TAG, "指定商品进行学习 》》》返回结果 : response = " + response);
                }
            }
        });
    }

    public class GoodsAdapter extends BaseQuickAdapter<GoodsBean, BaseViewHolder> {

        public GoodsAdapter(List<GoodsBean> list) {
            super(R.layout.adapter_item_goods, list);
        }

        @Override
        protected void convert(@NonNull BaseViewHolder holder, GoodsBean model) {
            if(model == null)return;
            Glide.with(MainActivity.this)
                    .load(model.getImageUrl())
                    .error(R.drawable.icon_photo_default)
                    .into((ImageView) holder.getView(R.id.ivGoodsImage));

            holder.setText(R.id.tvGoodsName, model.getGoodsName());
            holder.setText(R.id.tvGoodsCount, "x " + model.count);

            int priceInt = model.getUnitPrice() / 100;
            int mode = model.getUnitPrice() % 100;
            String mode1 = "" + mode;
            if (mode < 10) {
                mode1 = "0" + mode;
            } else if (mode % 10 == 0) {
                mode1 = String.valueOf(mode / 10);
            }
            holder.setText(R.id.tvGoodsPrice, String.format("%s元", mode == 0 ? priceInt : priceInt + "." + mode1));

            int goodsTotal = model.getUnitPrice() * model.count;
            int totalInt = goodsTotal / 100;
            mode = goodsTotal % 100;
            String mode2 = "" + mode;
            if (mode < 10) {
                mode2 = "0" + mode;
            }
            holder.setText(R.id.tvGoodsTotalPrice, String.format("%s.%s", totalInt, mode2));
        }
    }

    /**
     * 银歌AI识别SDK初始化
     */
    private void initAiSDK() {
        // 获取银歌AI识别SDK对象
        mYingeoAiSDK = YingeoAiSDK.getInstance();
        // 日志打开开关，默认为false，不打开日志
        MLog.setPrint(true);
        // SDK配置信息
        YingeoAiConfig config = buildSDKConfig();
        // 调用SDK初始化接口
        mYingeoAiSDK.initAiService(this, config, aiServiceCallback);
    }

    /**
     * 默认配置
     */
    public YingeoAiConfig buildSDKConfig() {
        YingeoAiConfig config = new YingeoAiConfig();
        // 识别输出结果数量，默认5个，取值范围1到10
        config.setOutputResultNumber(10);
        // 是否开启多目标识别，默认关闭
        config.setEnableMultipleTarget(true);
        // 是否支持实时学习，默认开启，只有开启后，调用aiLearnWithGoods方法才有学习的效果
        config.setEnableRealTimeLearning(true);
        return config;
    }

    /**
     * 银歌AI识别SDK回调
     */
    private IYingeoAIServiceCallback aiServiceCallback = new IYingeoAIServiceCallback() {
        @Override
        public void onInitSuccess() {
            // 银歌AI识别SDK初始化成功
            MLog.e(TAG, "银歌AI识别SDK初始化成功");

            // 同步商品数据到银歌AI识别SDK
            syncGoods2AiService();

            // 启用相机帧数据回调，
            // 看自己业务是否需要显示相机预览，如果不需要这里设置为false，开启会有一定的性能损耗。
            mYingeoAiSDK.setEnableAiCameraFrameDataCallback(true);
        }

        @Override
        public void onMessage(AiErrorMessage message) {
            // 银歌AI识别SDK相关业务信息回调
            MLog.e(TAG, "onMessage 》》》message = " + message);
            int code = message.getCode();
            // 银歌AI插件未安装
            if (code == ErrorCode.SDK_PLUGIN_NOT_INSTALL.code) {
                MLog.d(TAG, "AI插件未安装");
                mYingeoAiSDK.showPluginInstallDialog(MainActivity.this);
            }
            // 银歌AI插件安装成功
            if (code == ErrorCode.SDK_PLUGIN_INSTALL_SUCCESS.code) {
                MLog.d(TAG, "AI插件安装成功");
                // 重新初始化SDK
                mYingeoAiSDK.initAiService(MainActivity.this, buildSDKConfig(), aiServiceCallback);
            }
            // 银歌AI激活成功
            if (code == ErrorCode.ACTIVE_SUCCESS.code) {
                MLog.d(TAG, "银歌AI激活成功");
            }
            // 银歌AI识别插件有新版可以更新
            if (code == ErrorCode.PLUGIN_CAN_UPGRADE.code) {
                MLog.d(TAG, "银歌AI识别插件有新版可以更新，建议更新插件后再使用，非强制更新");
            }
            // 银歌AI识别插件有新版，必须更新后才能进行识别相关操作，为强制更新
            if (code == ErrorCode.PLUGIN_MUST_UPGRADE.code) {
                MLog.d(TAG, "银歌AI识别插件有新版，必须更新后才能进行识别相关操作，需要强制更新，否则无法识别商品");
                // 打开升级弹窗提醒用户升级插件
                mYingeoAiSDK.showPluginUpgradeDialog(MainActivity.this);
            }
        }

        @Override
        public void onAiRecognitionResult(List<AiRecognitionResult> result) {
            // 当调用银歌AI识别SDK的商品识别接口后，识别结果会在该回调方法中返回。
            MLog.d(TAG, "AI识别回调");
            if (ListUtils.isEmpty(result)) {
                MLog.d(TAG, "AI未识别到结果");
                goodsList.clear();
                handler.post(() -> goodsAdapter.notifyDataSetChanged());
                return;
            }
            goodsList.clear();
            for (AiRecognitionResult item : result) {
                GoodsBean goodsBean = null;
                for (GoodsBean emt : goodsList) {
                    if (emt.getGoodsCode().equals(item.getGoodsCode())) {
                        goodsBean = emt;
                        break;
                    }
                }
                if (goodsBean == null) {
                    goodsBean = GoodsDataSource.queryGoodsWithCode(item.getGoodsCode());
                    if (goodsBean != null) {
                        goodsBean.count = 1;
                    }
                    goodsList.add(goodsBean);
                } else {
                    goodsBean.count += 1;
                }
            }
            goodsResultSource = GoodsResultSource.AI_RECOGNITION;
            handler.post(() -> {
                totalCountView.setText(String.valueOf(goodsList.size()));
                int totalMoney = 0;
                for (GoodsBean emt : goodsList) {
                    totalMoney += emt.getUnitPrice();
                }
                int totalInt = totalMoney / 100;
                int mode = totalMoney % 100;
                String modeStr = "" + mode;
                if (mode < 10) {
                    modeStr = "0" + mode;
                }
                totalPrice = String.format("%s.%s", totalInt, modeStr);
                willPayView.setText(totalPrice + "元");
                realPayIntView.setText(String.format("￥%s.", totalInt));
                realPayFloatView.setText(modeStr);
                goodsAdapter.notifyDataSetChanged();
            });
        }

        @Override
        public void onCameraFrameChanged(Bitmap bitmap) {
            // 当setEnableAiCameraFrameDataCallback方法设置为true，该方法将会毁掉相机的预览帧图像数据
            MainHandler.runOnUiThread(() -> ivPreview.setImageBitmap(bitmap));
        }
    };

    private AiGoodsBean convertGoodsInfo2AiGoodsBean(GoodsBean goodsBean) {
        return new AiGoodsBean(goodsBean.getGoodsCode(), goodsBean.getGoodsName(), goodsBean.getUnitPrice(), goodsBean.getImageUrl());
    }

    /**
     * 同步商品到银歌AI识别SDK
     * 如果商品数量较多，建议分页传输，避免大数据量造成AIDL接口调用失败
     */
    private void syncGoods2AiService() {
        new Thread(() -> {
            List<GoodsBean> goodsBeanList = new ArrayList<>(GoodsDataSource.dataSource);

            List<AiGoodsBean> syncGoodsList = new ArrayList<>();
            for (GoodsBean goodsBean : goodsBeanList) {
                AiGoodsBean aiGoodsBean = new AiGoodsBean(goodsBean.getGoodsCode(), goodsBean.getGoodsName(), goodsBean.getUnitPrice(), goodsBean.getImageUrl());
                syncGoodsList.add(aiGoodsBean);
            }
            AiRemoteResponse response = mYingeoAiSDK.doSyncGoods(1, 1, syncGoodsList);
        }).start();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btnAiRecognition:
                executeAiRecognition();
                break;
            case R.id.btnAiSetting:
                // 打开AI设置页面
                mYingeoAiSDK.openAiSetting(AiSettingType.SETTING, null);

                // 打开商品学习搜索商品页面
//                mYingeoAiSDK.openAiSetting(AiSettingType.LEARN, null);

                // 打开商品学习指定商品学习页面
//                mYingeoAiSDK.openAiSetting(AiSettingType.LEARN, "1001");

                // 打开纠错页面
//                mYingeoAiSDK.openAiSetting(AiSettingType.FIX_ERROR, null);
                break;
            case R.id.sure_pay:
                if ("".equals(totalPrice)) {
                    return;
                }
                PayDialog dialog = new PayDialog(this, totalPrice);
                dialog.show();
                handler.sendEmptyMessageDelayed(3, 4000);
        }
    }

    /**
     * 调用SDK识别接口，触发AI识别，这是通过按钮模拟触发识别
     * 实际业务中，需根据自己的业务场景，选择合适的时机调用识别接口
     * 比如生鲜称重场景：当检测到电子秤重量稳定后，可以调用识别接口，触发识别。
     */
    private void executeAiRecognition() {
        AiRemoteResponse response = mYingeoAiSDK.aiRecognition();
        if (response != null && response.getCode() == ErrorCode.NOT_ACTIVE.code) {
            MLog.e(TAG, "指定商品进行学习 》》》SDK未激活，请先激活，才能完进行别功能");
//            openActivation();
            activation();
        }
    }

    /**
     * 打开银歌Ai识别SDK激活页面
     * 激活成功结果在{@link IYingeoAIServiceCallback#onMessage(AiErrorMessage)}中回调
     */
    private void openActivation() {
        // 店铺信息，填写当前设备店铺信息，联系人信息
        ActiveUserInfo userInfo = new ActiveUserInfo();
        userInfo.setShopName("银歌生鲜店");
        userInfo.setContacts("银歌");
        userInfo.setContactPhone("18000000001");
        mYingeoAiSDK.openActivation(userInfo);
    }

    /**
     * 通过激活码使用SDK接口进行激活
     */
    private void activation() {
        // 店铺信息，填写当前设备店铺信息，联系人信息
        ActiveUserInfo userInfo = new ActiveUserInfo();
        userInfo.setShopName("银歌生鲜店");
        userInfo.setContacts("银歌");
        userInfo.setContactPhone("18000000001");
        AiRemoteResponse response = mYingeoAiSDK.activation("将这里替换为您的激活码", userInfo);
        MLog.e(TAG, "通过激活码使用SDK接口进行激活 》》》response = " + response);
    }

    @Override
    protected void onDestroy() {
        mYingeoAiSDK.unInitAiService();
        super.onDestroy();
    }

}